package com.relytosoft.mizar.analyze.face.services.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.relytosoft.dubhe.common.core.base.page.PageQuery;
import com.relytosoft.dubhe.common.core.exception.ServiceException;
import com.relytosoft.dubhe.common.kafka.producer.KafkaOpMsg;
import com.relytosoft.dubhe.common.kafka.producer.KafkaProducer;
import com.relytosoft.mizar.analyze.base.constant.MediaMqConstants;
import com.relytosoft.mizar.analyze.base.entity.pojo.dto.TaskRequestDto;
import com.relytosoft.mizar.analyze.base.enums.DeleteStatusEnum;
import com.relytosoft.mizar.analyze.base.enums.TaskStatusEnum;
import com.relytosoft.mizar.analyze.face.api.entity.AyFaceTask;
import com.relytosoft.mizar.analyze.face.api.entity.AyFaceTaskSon;
import com.relytosoft.mizar.analyze.face.api.pojo.dto.AyTaskIdDto;
import com.relytosoft.mizar.analyze.face.api.pojo.query.AyFaceTaskSonQuery;
import com.relytosoft.mizar.analyze.face.services.mapper.AyFaceTaskSonMapper;
import com.relytosoft.mizar.analyze.face.services.service.AyFaceTaskService;
import com.relytosoft.mizar.analyze.face.services.service.AyFaceTaskSonService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author zyc
 * @date 2022/5/16 11:41
 */
@Service
public class AyFaceTaskSonServiceImpl extends ServiceImpl<AyFaceTaskSonMapper, AyFaceTaskSon> implements AyFaceTaskSonService {


    @Resource
    private AyFaceTaskSonMapper ayFaceTaskSonMapper;

    @Resource
    private AyFaceTaskService ayFaceTaskService;

    @Resource
    private KafkaProducer kafkaProducer;

    @Override
    public IPage<AyFaceTaskSon> selectAyFaceTaskSonPageList(PageQuery pageQuery, AyFaceTaskSonQuery ayFaceTaskSonQuery) {
        if (StrUtil.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("id");
            pageQuery.setIsAsc("desc");
        }
        return ayFaceTaskSonMapper.selectPageTaskSonList(pageQuery.build(), ayFaceTaskSonQuery);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean insertAyFaceTaskSon(AyFaceTaskSon ayFaceTaskSon) {
        Integer isDeleted = ayFaceTaskSonMapper.selectTaskSonById(ayFaceTaskSon.getCameraId());
        if (null != isDeleted) {
            throw new ServiceException("该通道已存在未删除的子任务");
        } else {
            boolean save = this.save(ayFaceTaskSon);
            return save;
        }
    }

    @Override
    public boolean updateAyFaceTaskSon(AyTaskIdDto ayTaskIdDto) {
        QueryWrapper<AyFaceTaskSon> wrapper = new QueryWrapper<>();
        wrapper.lambda().in(AyFaceTaskSon::getId, ayTaskIdDto.getIds())
                .ne(AyFaceTaskSon::getStatus, TaskStatusEnum.RUNING.getValue())
                .eq(AyFaceTaskSon::getIsDeleted, DeleteStatusEnum.NOT_DELETED.getValue());
        AyFaceTaskSon ayFaceTaskSon = new AyFaceTaskSon();
        ayFaceTaskSon.setIsDeleted(DeleteStatusEnum.DELETED.getValue());
        ayFaceTaskSon.setUpdatedId(ayTaskIdDto.getUpdatedId());
        ayFaceTaskSon.setUpdatedBy(ayTaskIdDto.getUpdatedBy());
        boolean update = this.update(ayFaceTaskSon, wrapper);
        return update;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean startAyFaceTaskSon(AyTaskIdDto ayTaskIdDto, AyFaceTaskSon ayFaceTaskSon) {
        if ((TaskStatusEnum.FINISHED.getValue() == ayFaceTaskSon.getStatus())
                && DeleteStatusEnum.NOT_DELETED.getValue() == ayFaceTaskSon.getIsDeleted()) {
            ayFaceTaskSon.setIsDeleted(DeleteStatusEnum.DELETED.getValue());
            ayFaceTaskSon.setUpdatedBy(ayTaskIdDto.getUpdatedBy());
            ayFaceTaskSon.setUpdatedId(ayTaskIdDto.getUpdatedId());
            this.updateById(ayFaceTaskSon);
            AyFaceTaskSon taskSon = createTaskSon(ayFaceTaskSon);
            boolean save = this.save(taskSon);
            if (save) {
                return true;
            }
        } else if (TaskStatusEnum.NOT_STARTED.getValue() == ayFaceTaskSon.getStatus()
                && DeleteStatusEnum.NOT_DELETED.getValue() == ayFaceTaskSon.getIsDeleted()) {
            ayFaceTaskSon.setStatus(TaskStatusEnum.CREATED.getValue());
            boolean update = this.updateById(ayFaceTaskSon);
            if (update) {
                return true;
            }
        }
        throw new ServiceException("不符合启动条件的结构化子任务");
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean stopAyFaceTaskSon(AyTaskIdDto ayTaskIdDto, AyFaceTaskSon ayFaceTaskSon) {
        //查询需要删除的数据
        if ((TaskStatusEnum.RUNING.getValue() == ayFaceTaskSon.getStatus())
                && DeleteStatusEnum.NOT_DELETED.getValue() == ayFaceTaskSon.getIsDeleted()) {
            ayFaceTaskSon.setStatus(TaskStatusEnum.FINISHED.getValue());
            ayFaceTaskSon.setUpdatedBy(ayTaskIdDto.getUpdatedBy());
            ayFaceTaskSon.setUpdatedId(ayTaskIdDto.getUpdatedId());
            ayFaceTaskSon.setEndTime(LocalDateTime.now());
            boolean update = this.updateById(ayFaceTaskSon);
            return update;
        }
        return false;
    }


    @Override
    public void insertFaceTaskSonKafkaOpMsg(TaskRequestDto taskRequestDto) {
        //发送新增子任务信息
        KafkaOpMsg kafkaOpMsg = new KafkaOpMsg();
        kafkaOpMsg.setOpType("insert");
        kafkaOpMsg.setData(JSONObject.toJSONString(taskRequestDto));
        kafkaProducer.send(MediaMqConstants.FACE_ANALYZE_TASK_TOPIC, JSONObject.toJSONString(kafkaOpMsg), true);
    }

    @Override
    public void deleteFaceTaskSonKafkaOpMsg(String taskId) {
        //发送需要删除子任务信息
        KafkaOpMsg kafkaOpMsg = new KafkaOpMsg();
        kafkaOpMsg.setData(taskId);
        kafkaOpMsg.setOpType("delete");
        kafkaProducer.send(MediaMqConstants.FACE_ANALYZE_TASK_TOPIC, JSONObject.toJSONString(kafkaOpMsg), true);
    }


    @Override
    public TaskRequestDto createRequest(AyFaceTaskSon ayFaceTaskSon) {
        TaskRequestDto taskRequestDto = new TaskRequestDto();
        taskRequestDto.setId(ayFaceTaskSon.getId());
        taskRequestDto.setDeviceId(ayFaceTaskSon.getCameraId());
        taskRequestDto.setDeviceName(ayFaceTaskSon.getCameraName());
        taskRequestDto.setRtspUrl(ayFaceTaskSon.getVideoUrl());
        taskRequestDto.setTaskName(ayFaceTaskSon.getTaskName());
        return taskRequestDto;
    }

    @Override
    public AyFaceTaskSon createTaskSon(AyFaceTaskSon ayFaceTaskSon) {
        AyFaceTaskSon taskSon = new AyFaceTaskSon();
        taskSon.setFaceTaskId(ayFaceTaskSon.getFaceTaskId());
        taskSon.setTaskName(ayFaceTaskSon.getTaskName());
        taskSon.setCameraId(ayFaceTaskSon.getCameraId());
        taskSon.setCameraName(ayFaceTaskSon.getCameraName());
        taskSon.setVideoUrl(ayFaceTaskSon.getVideoUrl());
        taskSon.setStatus(TaskStatusEnum.CREATED.getValue());
        taskSon.setIsDeleted(DeleteStatusEnum.NOT_DELETED.getValue());
        return taskSon;
    }

    @Override
    public List<AyFaceTaskSon> selectByFaceTaskId(Integer id) {
        QueryWrapper<AyFaceTaskSon> wrapper = new QueryWrapper<>();
        wrapper.lambda().in(AyFaceTaskSon::getFaceTaskId, id);
        return this.baseMapper.selectList(wrapper);
    }


    @Override
    public Integer getFaceTaskId(List<AyFaceTaskSon> ayFaceTaskSons) {
        for (int i = 0; i < ayFaceTaskSons.size(); i++) {
            if (ayFaceTaskSons.get(0).getFaceTaskId() != ayFaceTaskSons.get(i).getFaceTaskId()) {
                throw new ServiceException("传入的子任务不属于同一主任务");
            }
        }
        return ayFaceTaskSons.get(0).getFaceTaskId();
    }

    @Override
    public void updateTaskStatus(Integer structureTaskId) {
        AyFaceTask ayFaceTask = ayFaceTaskService.getById(structureTaskId);
        if (ayFaceTaskSonMapper.selectStatusList(structureTaskId).stream().allMatch(item -> item == TaskStatusEnum.FINISHED.getValue())) {
            ayFaceTask.setStatus(TaskStatusEnum.FINISHED.getValue());
        }
    }
}
